home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Die Speccy' 97
/
Die Speccy' 97.iso
/
amiga_system
/
the_aminet
/
util
/
cli
/
whence.lha
/
WHENCE
/
Whence.c
< prev
Wrap
C/C++ Source or Header
|
1995-10-31
|
14KB
|
817 lines
#define VERSION "1.4 "
/**
***** Whence
*
***** Searches all directories in AmigaDos PATH for the given
* command name, and reports all instances found.
*
* Directories of the same name are ignored.
*
* The first instance printed would be the one AmigaDos executes.
*
* Handles from 1.2 upwards. 2.04 Internals/residents
* are reported.
*
* Redundant paths are NOT reported (in contrast with AmigaDos 'which')
*
* Path, File size and date is printed.
*
* Algorithms depend entirely on observed format of
* Path and Assign commands executed under AmigaDos 2.04 , i.e
* it is assumed that they follow previous releases.
*
*
*
*
***** Written by Gary Duncan
*
* Bug reports etc via e-mail to gduncan@werple.net.au
*
*
***** Freely distributable for non-commercial purposes.
* Please keep this header intact.
*
*
* Compiles under SAS 6.2
*
* Formatted with 'indent -gnu' ; a big time-saving program.
*
***** Function List :-
brk
main
chk_cdir
put_path
get_fib
get_cwd
add_C_assign
search_resident
dss2str
usage
hexit
Version Date Changes
~~~~~~~ ~~~~ ~~~~~~
1.0 29Oct93 Original release
1.1 24Jan94 used __AMIGADATE__
1.2 28Nov94 uses manual __AMIGADATE__ (buggy)
1.3 27Apr95 reactivated __AMIGADATE__ , corrected exit state
1.4 30Sep95 No code changed ( comments corrected)
*************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <dos.h>
#include <ctype.h>
#include <exec/execbase.h>
#include <exec/types.h>
#include <string.h>
#include <time.h>
#include <exec/memory.h>
#include <libraries/dosextens.h>
#include <proto/dos.h>
#include <clib/intuition_protos.h>
#include <clib/utility_protos.h>
#include <proto/exec.h>
#include <devices/serial.h>
#include <devices/timer.h>
#include <exec/io.h>
#include <utility/date.h>
#include "typedefs.h"
#include "whence_protos.h"
#define REDUNDANT ((char *) -1)
/*
* string for AmigaDOS Version Command
*/
char A_vers[] = "\0$VER: whence\t" VERSION __AMIGADATE__;
LIBRARY *UtilityBase = NULL;
LIBRARY *BattClockBase;
FILE *fp_P = NULL;
FILE *fp_A = NULL;
FILE *fp_R = NULL;
FILE *fp_CD = NULL;
static char file_P[20];
static char file_A[20];
static char file_R[20];
static char file_CD[20];
FILEINFOBLOCK *fib = NULL;
char *paths[64]; /* assume max of 64 dirs in Path */
int path_cnt = 0;
BOOLEAN c_flag = FALSE;
int break_flag;
int
brk (void)
{
break_flag++;
return 0;
}
/*************************************************************************/
int
main (int argc, char **argv)
{
static char buf[256];
static char line_buf[256];
LIBRARY *lp;
char *fname = argv[1];
char *str;
char **PP;
/*
* set up ^C processing
*/
if (onbreak (&brk))
{
printf ("onbreak fail\n");
exit (1);
}
if (argc != 2)
{
fprintf (stderr, "Error: need a command name\n");
usage ();
hexit (1);
}
if (*argv[1] == '-')
{
usage ();
hexit (1);
}
/*
* get a FIB
*/
fib = AllocMem ((long) sizeof (*fib), MEMF_CLEAR);
if (fib == NULL)
{
fprintf (stderr, "unable to allocate space for fileinfo block\n");
hexit (1);
}
/*
* if below 2.04 version, we won't look for Residents (or itinerants :)
*/
if (lp = OpenLibrary ("exec.library", 37L))
{
CloseLibrary (lp);
/*
* build Resident File
*/
sprintf (file_R, "T:wr_%08d", file_R);
sprintf (buf, "RESIDENT >%s", file_R);
Execute (buf, 0L, 0L);
if ((fp_R = fopen (file_R, "r")) == NULL)
{
fprintf (stderr, "Can't fopen %s\n", file_R);
hexit (1);
}
}
/*
* build file containing CD
*/
sprintf (file_CD, "T:wcd_%08d", file_CD);
sprintf (buf, "CD >%s", file_CD);
Execute (buf, 0L, 0L);
/*
* build file containing PATHS
*/
sprintf (file_P, "T:wp_%08d", file_P);
sprintf (buf, "PATH >%s", file_P);
Execute (buf, 0L, 0L);
/*
* build file containing ASSIGNS
*/
sprintf (file_A, "T:wa_%08d", file_A);
sprintf (buf, "ASSIGN >%s", file_A);
Execute (buf, 0L, 0L);
/*
* open the files for further manipulation , later
*/
if ((fp_P = fopen (file_P, "r")) == NULL)
{
fprintf (stderr, "Can't fopen %s\n", file_P);
hexit (1);
}
if ((fp_A = fopen (file_A, "r")) == NULL)
{
fprintf (stderr, "Can't fopen %s\n", file_A);
hexit (1);
}
if ((fp_CD = fopen (file_CD, "r")) == NULL)
{
fprintf (stderr, "Can't fopen %s\n", file_CD);
hexit (1);
}
/*
***************************************************************
*/
/*
* if Resident file open, search and report on it first
* - that's the rules under 2.04
*/
if (fp_R)
search_resident (fname);
/*
* put Path strings into an *array for convenience
*
*/
path_cnt = 0;
while ((str = fgets (line_buf, sizeof (line_buf), fp_P)) != NULL)
{
char *p;
/*
* handle "Current directory"
*/
if (path_cnt == 0)
{
str = get_cwd ();
}
p = &str[strlen (str) - 1];
*p = '\0'; /* remove NL */
/*
* C: is last. Drop it now, handle later
*/
if (strcmp (str, "C:") == 0)
{
continue;
}
/*
* copy it to a malloc'd bit of memory
*/
put_path (str);
}
/*
* now handle case where current dir is in Path list
*/
chk_cdir ();
/*
* now handle C: (last). If 2.04 may be added dirs (+ xxx)
*/
add_C_assign ();
/*
* now scan recreated path list
*/
for (PP = paths; *PP; ++PP)
{
char buf[256];
if (*PP == REDUNDANT)
{
continue;
}
strcpy (buf, *PP);
if (buf[strlen (buf) - 1] != ':')
{
strcat (buf, "/");
}
strcat (buf, fname);
chkabort ();
if (break_flag)
{
fprintf (stderr, "^C\n");
hexit (1);
}
if (get_fib (buf) == NULL)
{
#if 0
printf ("Not a File (%s)\n", buf);
#endif
continue;
}
/*
* make sure its a file not dir
*/
if (fib->fib_DirEntryType < 0)
{
/*
* print pathname , size , date
*/
printf ("%-25s %7d bytes : %s\n", buf, fib->fib_Size,
dss2str (&fib->fib_Date));
}
}
hexit (0);
}
/***************************************************************************
Name: chk_cdir
Purpose: checks paths[] to see if current dir entry (#1)
is replicated below, if so mark as redundant that entry.
Entry :
Returns :
****************************************************************************/
void
chk_cdir ()
{
int j;
for (j = 1; j < path_cnt; ++j)
{
if (stricmp (paths[0], paths[j]) == 0)
{
#if 0
printf ("%s : REDUNDANT\n", paths[j]);
#endif
free (paths[j]);
paths[j] = REDUNDANT;
return;
}
}
}
/***************************************************************************
Name: put_path
Purpose: copies given string to malloc'd memory and put
its pointer in next slot in paths[].
Entry :
Returns :
****************************************************************************/
void
put_path (char *str)
{
if (path_cnt == sizeof (paths))
{
fprintf (stderr, "path buffer (64) full!\n");
hexit (1);
}
if ((paths[path_cnt] = malloc (strlen (str) + 1)) == NULL)
{
fprintf (stderr, "malloc fail\n");
hexit (1);
}
strcpy (paths[path_cnt++], str);
#if 0
printf ("put_path : %s\n", paths[path_cnt - 1]);
#endif
}
/***************************************************************************
Name: get_fib
Purpose: given a file name, return with a FIB ,
or NULL if non-existent
Entry :
Returns :
****************************************************************************/
FILEINFOBLOCK *
get_fib (char *fname)
{
BPTR flock;
if (!(flock = Lock (fname, ACCESS_READ)))
{
return NULL;
}
if (!Examine (flock, fib))
{
UnLock (flock);
return NULL;
}
UnLock (flock);
return fib;
}
/***************************************************************************
Function : get_cwd
Purpose: returns with path to current dir
Entry :
Returns :
****************************************************************************/
char *
get_cwd ()
{
static char buf[128];
if (fgets (buf, sizeof (buf), fp_CD) == NULL)
{
fprintf (stderr, "fatal error reading cwd\n");
hexit (1);
}
return buf;
}
/***************************************************************************
Function : add_C_assign
Purpose: scans Assign file and adds C: info to path[]
Entry :
Returns :
****************************************************************************/
void
add_C_assign ()
{
static char buf[128];
BOOLEAN flag = FALSE;
char *p;
int p_c;
int j;
if (fseek (fp_A, 0L, SEEK_SET) == -1)
{
fprintf (stderr, "\nget_assign seek error\n");
hexit (1);
}
while (1)
{
if (fgets (buf, sizeof (buf), fp_A) == NULL)
{
return;
}
buf[strlen (buf) - 1] = '\0'; /* zap NL */
/*
* point to start of last field (dir)
*/
p = &buf[strlen (buf) - 1];
while (*(p - 1) != ' ')
--p;
/*
* when c is found , put its dirs into paths[]
*/
if (strnicmp (buf, "c ", 2) == 0)
{
flag = TRUE;
p_c = path_cnt; /* hold index */
put_path (p);
}
else if (flag)
{
if (*(p - 2) == '+')
{
put_path (p);
}
else
/* end */
{
/*
* now scan paths[] to see if c: was already there (above in
* array). If so mark as redundant c: dir
*/
for (j = 0; j < p_c; ++j)
{
if (strcmp (paths[j], paths[p_c]) == 0)
{
/*
* found a matching dir, mark it as a null
*/
free (paths[p_c]);
paths[p_c] = REDUNDANT;
return;
}
}
}
}
}
}
/***************************************************************************
Function : search_resident
Purpose: searches for resident commands
Entry :
Returns :
****************************************************************************/
void
search_resident (char *name)
{
char buf[80];
/*
* skip first line
*/
if (fgets (buf, sizeof (buf), fp_R) == NULL)
{
return;
}
/*
* skip second line
*/
if (fgets (buf, sizeof (buf), fp_R) == NULL)
{
return;
}
while (1)
{
char *p = buf;
if (fgets (buf, sizeof (buf), fp_R) == NULL)
{
return;
}
while (*++p != ' ');
*p = '\0';
if (strlen (name) == strlen (buf))
{
if (stricmp (name, buf) == 0)
{
while (*++p == ' ');
if (isdigit (*p))
printf ("RES %s\n", name);
else
printf ("INTERNAL %s\n", name);
return;
}
}
}
}
/***************************************************************************
Function : dss2str
Purpose: generates a date string
Entry : Datestamp
Returns : ptr to date string
****************************************************************************/
char *
dss2str (DATESTAMP * ds)
{
static DM days_month[] =
{
31, "Jan",
28, "Feb",
31, "Mar",
30, "Apr",
31, "May",
30, "Jun",
31, "Jul",
31, "Aug",
30, "Sep",
31, "Oct",
30, "Nov",
31, "Dec",
};
static char buf[40];
struct tm Time;
int j;
long time, ago;
/*
* convert to a secs
*/
time = ds->ds_Days * (24 * 60 * 60);
time += ds->ds_Minute * 60;
time += ds->ds_Tick / TICKS_PER_SECOND;
Time.tm_sec = time % 60;
time /= 60;
Time.tm_min = time % 60;
time /= 60;
Time.tm_hour = time % 24;
time /= 24;
Time.tm_wday = time % 7;
Time.tm_year = 78 + (time / (4 * 365 + 1)) * 4;
time %= 4 * 365 + 1;
while (time)
{
ago = 365;
if ((Time.tm_year & 3) == 0) /* leap year */
ago++;
if (time < ago)
break;
time -= ago;
Time.tm_year++;
}
Time.tm_yday = ++time;
for (j = 0; j < 12; j++)
{
ago = days_month[j].days;
if (j == 1 && (Time.tm_year & 3) == 0) /* Feb , and leap year ? */
ago++;
if (time <= ago)
break;
time -= ago;
}
Time.tm_mon = j;
Time.tm_mday = time;
/* date format : 23-dec-88 22:33:01 */
sprintf (buf, "%02d-%s-%2d %02d:%02d:%02d",
Time.tm_mday,
days_month[Time.tm_mon].months,
Time.tm_year,
Time.tm_hour,
Time.tm_min,
Time.tm_sec
);
return (buf);
}
/***************************************************************************
Function : usage
Purpose: prints usage
Entry :
Returns :
****************************************************************************/
void
usage ()
{
static char *rats[] =
{
"usage: whence <command>",
"" /* empty string ;TERM */
};
int j = 0;
char *ptr;
fprintf (stderr,
/****/ "Whence: prints paths to given command in AmigaDos search path\n\n\
Version %s [%s] written by gduncan@philips.oz.au\n", VERSION, __DATE__);
while (*(ptr = rats[j++]))
fprintf (stderr, "%s\n", ptr);
}
/***************************************************************************
Function : hexit
Purpose: cleans up and exits
Entry :
Returns :
****************************************************************************/
void
hexit (int k)
{
int j;
fclose (fp_R);
unlink (file_R);
fclose (fp_CD);
unlink (file_CD);
fclose (fp_P);
unlink (file_P);
fclose (fp_A);
unlink (file_A);
if (fib)
FreeMem (fib, (long) sizeof (*fib));
/*
* release path array memory
*/
for (j = 0; j < path_cnt; ++j)
{
char *p = paths[j];
if (p && (p != REDUNDANT))
free (p);
}
exit (k);
}
/*--*/
Ç